home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / edit / jwpsrc.zip / UNDO.C < prev   
C/C++ Source or Header  |  1993-03-31  |  27KB  |  1,066 lines

  1. /* Copyright (C) Stephen Chung, 1991-1993.  All rights reserved. */
  2.  
  3. #include "jwp.h"
  4.  
  5.  
  6. static PARAGRAPH far *fpara = NULL;
  7.  
  8.  
  9.  
  10. void FreeUndo (UNDOBUF far *up)
  11. {
  12.     switch (up->action) {
  13.         U_PARAFORMAT:
  14.         U_INSERT:
  15.         U_DELETE:
  16.         U_REPLACE: {
  17.             PARAGRAPH far *lp, far *lp2;
  18.  
  19.             for (lp = (PARAGRAPH far *) up->data; lp != NULL; ) {
  20.                 if (lp->text != NULL) FreeBlock(lp->text);
  21.                 lp2 = lp;
  22.                 lp = lp->next;
  23.                 FreeBlock(lp2);
  24.             }
  25.         }
  26.     }
  27.     FreeBlock(up);
  28. }
  29.  
  30.  
  31.  
  32. void FreeUndoChain (UNDOBUF far *up)
  33. {
  34.     UNDOBUF far *up1;
  35.  
  36.     for (; up != NULL; ) {
  37.         up1 = up;
  38.         up = up->next;
  39.         FreeUndo(up1);
  40.     }
  41. }
  42.  
  43.  
  44.  
  45. static int FindParaNum (FILEOPTIONS *f, PARAGRAPH far *p)
  46. {
  47.     int n;
  48.     PARAGRAPH far *p1;
  49.  
  50.     for (p1 = f->paragraph, n = 0; p1 != NULL; p1 = p1->next, n++) {
  51.         if (p1 == p) return (n);
  52.     }
  53.  
  54.     return (-1);
  55. }
  56.  
  57.  
  58.  
  59. void TrimUndoChain (FILEOPTIONS *f)
  60. {
  61.     UNDOBUF far *up;
  62.  
  63.     if (f->undo == NULL) return;
  64.  
  65.     while (f->undolevels > global.undolevels) {
  66.         if (f->undo->next == NULL) {
  67.             FreeUndo(f->undo);
  68.             f->undo = f->undotail = NULL;
  69.             f->undolevels = 0;
  70.             return;
  71.         }
  72.  
  73.         up = f->undotail->prev;
  74.         FreeUndo(f->undotail);
  75.         if (up == NULL) {
  76.             f->undo = f->undotail = NULL;
  77.             f->undolevels = 0;
  78.         } else {
  79.             up->next = NULL;
  80.             f->undotail = up;
  81.             f->undolevels--;
  82.         }
  83.     }
  84. }
  85.  
  86.  
  87.  
  88. static UNDOBUF far *CreateUndo (int para, int start, int len, UNDOACTIONS action)
  89. {
  90.     UNDOBUF far *up;
  91.  
  92.     up = StructAlloc(UNDOBUF);
  93.  
  94.     up->para1 = up->para2 = para;
  95.     up->start = start;
  96.     up->stop = start + len;
  97.     up->action = action;
  98.     up->data = NULL;
  99.     up->next = up->prev = NULL;
  100.  
  101.     return (up);
  102. }
  103.  
  104.  
  105.  
  106. void UndoAddTyping (FILEOPTIONS *f, POSITION p, int howmany, BOOL splitline)
  107. {
  108.     int para, start;
  109.     UNDOBUF far *up;
  110.     time_t tm;
  111.  
  112.  
  113.     if (global.undolevels == 0) return;
  114.     if (!(f->type & FN_NORMAL)) return;
  115.  
  116.     FreeUndoChain(f->redo);
  117.     f->redo = NULL;
  118.  
  119.     para = FindParaNum(f, PARAOF(p));
  120.     start = POS2ABS(p);
  121.  
  122.     up = f->undo;
  123.  
  124.     if (splitline) {
  125.         if (up == NULL) {
  126.             up = f->undo = f->undotail = CreateUndo(para, start, 0, U_INSERT);
  127.             up->para2 = para + 1;
  128.             up->stop = 0;
  129.             f->undolevels = 1;
  130.         } else if ((up->action == U_INSERT || up->action == U_REPLACE) &&
  131.                    up->para2 == para && up->stop == start) {
  132.             up->para2 = para + 1;
  133.             up->stop = 0;
  134.         } else {
  135.             up = CreateUndo(para, start, 0, U_INSERT);
  136.             up->para2 = para + 1;
  137.             up->stop = 0;
  138.             up->next = f->undo;
  139.             f->undo->prev = up;
  140.             f->undo = up;
  141.             f->undolevels++;
  142.             TrimUndoChain(f);
  143.         }
  144.     } else {
  145.         if (up == NULL) {
  146.             up = f->undo = f->undotail = CreateUndo(para, start, howmany, U_INSERT);
  147.             f->undolevels = 1;
  148.         } else if ((up->action != U_INSERT && up->action != U_REPLACE) ||
  149.                    up->para2 != para || up->stop != start) {
  150.  
  151.             up = CreateUndo(para, start, howmany, U_INSERT);
  152.             up->next = f->undo;
  153.             f->undo->prev = up;
  154.             f->undo = up;
  155.             f->undolevels++;
  156.             TrimUndoChain(f);
  157.         } else {
  158.             up->stop += howmany;
  159.         }
  160.     }
  161.  
  162.     time(&tm);
  163.     up->time = tm;
  164. }
  165.  
  166.  
  167.  
  168. void UndoFixConvert (FILEOPTIONS *f, POSITION p, int oldlen, int newlen)
  169. {
  170.     UNDOBUF far *up;
  171.     time_t tm;
  172.  
  173.     if (global.undolevels == 0) return;
  174.     if (f->undo == NULL) return;
  175.     if (!(f->type & FN_NORMAL)) return;
  176.  
  177.     up = f->undo;
  178.     if (up->action != U_INSERT && up->action != U_REPLACE) return;
  179.     if (up->para2 != FindParaNum(f, PARAOF(p))) return;
  180.     //if (up->stop != POS2ABS(p) + oldlen) return;
  181.     if (up->stop <= POS2ABS(p)) return;
  182.  
  183.     up->stop += newlen - oldlen;
  184.  
  185.     time(&tm);
  186.     up->time = tm;
  187. }
  188.  
  189.  
  190.  
  191. void UndoAddInsert (FILEOPTIONS *f, POSITION p1, POSITION p2)
  192. {
  193.     UNDOBUF far *up;
  194.     int para1, para2;
  195.     time_t tm;
  196.  
  197.     if (global.undolevels == 0) return;
  198.     if (!(f->type & FN_NORMAL)) return;
  199.  
  200.     FreeUndoChain(f->redo);
  201.     f->redo = NULL;
  202.  
  203.     para1 = FindParaNum(f, PARAOF(p1));
  204.     para2 = FindParaNum(f, PARAOF(p2));
  205.  
  206.     if (f->undo == NULL) {
  207.         up = f->undo = f->undotail = CreateUndo(para1, POS2ABS(p1), 0, U_INSERT);
  208.         up->para2 = para2;
  209.         up->stop = POS2ABS(p2);
  210.         f->undolevels = 1;
  211.     } else {
  212.         up = CreateUndo(para1, POS2ABS(p1), 0, U_INSERT);
  213.         up->para2 = para2;
  214.         up->stop = POS2ABS(p2);
  215.         up->next = f->undo;
  216.         f->undo->prev = up;
  217.         f->undo = up;
  218.         f->undolevels++;
  219.         TrimUndoChain(f);
  220.     }
  221.  
  222.     time(&tm);
  223.     up->time = tm;
  224. }
  225.  
  226.  
  227.  
  228. static PARAGRAPH far *SaveData (FILEOPTIONS *f, POSITION p1, POSITION p2)
  229. {
  230.     unsigned int len;
  231.     PARAGRAPH far *data = NULL, far *p, far *lp;
  232.  
  233.     if (PARAOF(p1) == PARAOF(p2)) {
  234.         lp = StructAlloc(PARAGRAPH);
  235.         _fmemcpy(lp, PARAOF(p1), sizeof(PARAGRAPH));
  236.  
  237.         lp->lines = lp->lastline = NULL;
  238.         lp->next = lp->prev = NULL;
  239.         len = POSOF(p2) - POSOF(p1);
  240.  
  241.         lp->textsize = (len + 2) * sizeof(UNIT);
  242.         lp->text = BlockAlloc(lp->textsize);
  243.  
  244.         _fmemcpy(lp->text, PARAOF(p1)->text + POSOF(p1), len * sizeof(UNIT));
  245.         lp->text[len].kanji = 0;
  246.  
  247.         return (lp);
  248.     }
  249.  
  250.     for (p = PARAOF(p1); ; p = p->next) {
  251.         if (data == NULL) {
  252.             data = lp = StructAlloc(PARAGRAPH);
  253.             _fmemcpy(lp, p, sizeof(PARAGRAPH));
  254.             lp->prev = NULL;
  255.         } else {
  256.             lp->next = StructAlloc(PARAGRAPH);
  257.             _fmemcpy(lp->next, p, sizeof(PARAGRAPH));
  258.             lp->next->prev = lp;
  259.             lp = lp->next;
  260.         }
  261.  
  262.         lp->next = NULL;
  263.         lp->lines = lp->lastline = NULL;
  264.  
  265.         if (p == PARAOF(p1)) {
  266.             len = unitlen(p->text) - POSOF(p1);
  267.             lp->textsize = (len + 2) * sizeof(UNIT);
  268.             lp->text = BlockAlloc(lp->textsize);
  269.             _fmemcpy(lp->text, p->text + POSOF(p1), len * sizeof(UNIT));
  270.             lp->text[len].kanji = 0;
  271.         } else if (p == PARAOF(p2)) {
  272.             len = POSOF(p2);
  273.             lp->textsize = (len + 2) * sizeof(UNIT);
  274.             lp->text = BlockAlloc(lp->textsize);
  275.             _fmemcpy(lp->text, p->text, len * sizeof(UNIT));
  276.             lp->text[len].kanji = 0;
  277.             break;
  278.         } else {
  279.             len = unitlen(p->text);
  280.             lp->textsize = (len + 2) * sizeof(UNIT);
  281.             lp->text = BlockAlloc(lp->textsize);
  282.             _fmemcpy(lp->text, p->text, len * sizeof(UNIT));
  283.             lp->text[len].kanji = 0;
  284.         }
  285.     }
  286.  
  287.     return (data);
  288. }
  289.  
  290.  
  291.  
  292. void UndoAddDelete (FILEOPTIONS *f, POSITION p1, POSITION p2)
  293. {
  294.     UNDOBUF far *up;
  295.     int para1, para2;
  296.     time_t tm;
  297.  
  298.     if (global.undolevels == 0) return;
  299.     if (!(f->type & FN_NORMAL)) return;
  300.  
  301.     FreeUndoChain(f->redo);
  302.     f->redo = NULL;
  303.  
  304.     para1 = FindParaNum(f, PARAOF(p1));
  305.     POSOF(p1) = POS2ABS(p1);
  306.     para2 = FindParaNum(f, PARAOF(p2));
  307.     POSOF(p2) = POS2ABS(p2);
  308.  
  309.     if (f->undo == NULL) {
  310.         up = f->undo = f->undotail = CreateUndo(para1, POSOF(p1), 0, U_DELETE);
  311.         up->para2 = para2;
  312.         up->stop = POSOF(p2);
  313.         f->undolevels = 1;
  314.     } else {
  315.         up = CreateUndo(para1, POSOF(p1), 0, U_DELETE);
  316.         up->para2 = para2;
  317.         up->stop = POSOF(p2);
  318.         up->next = f->undo;
  319.         f->undo->prev = up;
  320.         f->undo = up;
  321.         f->undolevels++;
  322.         TrimUndoChain(f);
  323.     }
  324.  
  325.     up->data = SaveData(f, p1, p2);
  326.  
  327.     time(&tm);
  328.     up->time = tm;
  329. }
  330.  
  331.  
  332.  
  333. void UndoJoinLine (FILEOPTIONS *f, POSITION p)
  334. {
  335.     int para, start;
  336.     UNDOBUF far *up;
  337.     PARAGRAPH far *pp;
  338.     time_t tm;
  339.  
  340.  
  341.     if (global.undolevels == 0) return;
  342.     if (!(f->type & FN_NORMAL)) return;
  343.  
  344.  
  345.     para = FindParaNum(f, PARAOF(p));
  346.     start = POS2ABS(p);
  347.  
  348.     up = f->undo;